/*
 * kalkulator_infix.cpp
 *
 *  Created on: Mar 5, 2009
 *      Author: karol
 */

#include <iostream>
#include <stack>
#include <cstdlib>

#include "definicje.h"

extern int value;
extern int charCount;
int getLeksem();

int T();
int G(int);
int E();
int H(int);
int F();

void error() {
	std::cerr << "Niepoprawne wejscie - znak nr : " << charCount << ". Koncze dzialanie" << std::endl;
	exit(1);
}

int buf = -1;
int topLeksem() {
	if(buf < 0 ) {
		buf = getLeksem();
	}
	return buf;
}

void next() {
	buf = -1;
}



//G -> + T G | - T G | e

int G(int val) {
	int a,b;
	int c = topLeksem();
	std::cerr << "G() --> " << std::endl;
	switch(c) {
		case PLUS:
			std::cerr << "G() --> plus" << std::endl;
			next();
			a = T();
			b = G(val + a);
			return b;
			break;
		case MINUS:
			std::cerr << "G() --> minus" << std::endl;
			next();
			a = T();
			b = G(val - a);
			return b;
			break;
		default:
			return val;  // To jest istotne ! Rozwijanie do e
	}
}

//H -> * F H | / F H | % F H | e
int H(int val) {
	int a,b;
	int c = topLeksem();
	std::cerr << "H() --> " << std::endl;
	switch(c) {
		case RAZY:
			std::cerr << "H() --> razy" << std::endl;
			next();
			a = F();
			b = H(val * a);
			return b;
			break;
		case PODZIEL:
			std::cerr << "H() --> podziel" << std::endl;
			next();
			a = F();
			if (a == 0) error();
			b = H(val / a);
			return b;
			break;
		case MODULO:
			std::cerr << "H() --> modulo" << std::endl;
			next();
			a = F();
			if (a == 0) error();
			b = H(val % a);
			return b;
			break;
		default:
			return val;  // To jest istotne ! Rozwijanie do e
	}
}

// To definicja dla F
// F -> liczba | ( E )
int F() {
	int a;
	int c = topLeksem();
	std::cerr << "F() --> " << std::endl;
	switch(c) {
		case NUM:
			std::cerr << "F() --> liczba" << std::endl;
			next();
			return value;
			break;
		case NLEWY:
			std::cerr << "F() --> Lewy" << std::endl;
			next();
			a = E();
			if(topLeksem() != NPRAWY) error();
			std::cerr << "F() --> PRAWY" << std::endl;
			next();
			return a;
			break;
		default:
			error();
	}
}

// E -> T G
int E() {
	int a,b;
	std::cerr << "E() --> " << std::endl;
	a = T();
	b = G(a);
	return b;
}


// T -> F H
int T() {
	int a,b;
	std::cerr << "T() --> " << std::endl;
	a = F();
	b = H(a);
	return b;
}

int main() {
	std::cout << E() << std::endl;
}
